home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr48 / pas_0593.zip / RB.PAS < prev    next >
Pascal/Delphi Source File  |  1993-05-30  |  7KB  |  252 lines

  1. {─ Fido Pascal Conference ────────────────────────────────────────────── PASCAL ─
  2. Msg  : 389 of 412
  3. From : Steve Gabrilowitz                   1:363/1701.0         15 May 93  21:59
  4. To   : Jeff Carney
  5. Subj : HELP! - File Pos.
  6. ────────────────────────────────────────────────────────────────────────────────
  7.  
  8. In a message to All <05-13-93 02:01> Jeff Carney wrote:
  9.  
  10. JC>  Can anyone help me figure out how I can move a TEXT file position
  11. JC>  pointer backwards instead of forwards?
  12.  
  13. I have a little file on my board that purports to read a text file backwards, I
  14. have never tried it but since it's so small I'll just post it here.  The ZIP
  15. contains two files, RB.PAS and TESTRB.PAS.  First, RB.PAS:}
  16.  
  17. {$R-,S-,I-}
  18.  
  19. {
  20.  Turbo Pascal 4.0 unit to read text files backwards.
  21.  
  22.  See TESTRB.PAS for a test and demonstration program. Routines here
  23.  are used in a manner very similar to normal text file read routines
  24.  except that the "reset" positions to the end of the file, and each
  25.  subsequent "readln" returns the prior line in the file until the
  26.  beginning of the file is reached.
  27.  
  28.  Each string returned by ReadLnBack is in normal forward order.
  29.  
  30.  One quirk will occur if an attempt is made to read from files with
  31.  lines longer than 255 characters. In this case ReadLnBack will return
  32.  the _last_ 255 characters of each such line rather than the first. This
  33.  is in keeping with the backwards nature of the unit, however.
  34.  
  35.  Hope someone finds a use for this!
  36.  
  37.  Written 6/7/88, Kim Kokkonen, TurboPower Software.
  38.  Released to the public domain.
  39. }
  40.  
  41. unit RB;
  42.   {-Read text files backwards}
  43.  
  44. interface
  45.  
  46. type
  47.   BackText = file;                {We use the UserData area in the untyped file
  48.  
  49. procedure AssignBack(var F : BackText; Fname : string);
  50.   {-Assign a backwards file to a file variable}
  51.  
  52. procedure ResetBack(var F : BackText; BufSize : Word);
  53.   {-Reset a backwards file, allocating buffer space (128 bytes or greater)}
  54.  
  55. procedure ReadLnBack(var F : BackText; var S : string);
  56.   {-Read next line from end of backwards file}
  57.  
  58. procedure CloseBack(var F : BackText);
  59.   {-Close backwards file, releasing buffer}
  60.  
  61. function BoF(var F : BackText) : Boolean;
  62.   {-Return true when F is positioned at beginning of file}
  63.  
  64. function BackResult : Word;
  65.   {-Return I/O status code from operation}
  66.  
  67.   {======================================================================}
  68.  
  69. implementation
  70.  
  71. const
  72.   LF = #10;
  73.  
  74. type
  75.   BufferArray = array[1..65521] of Char;
  76.   BackRec =                       {Same as Dos.FileRec, with UserData filled in
  77.     record
  78.       Handle : Word;
  79.       Mode : Word;
  80.       RecSize : Word;
  81.       Private : array[1..26] of Byte;
  82.       Fpos : LongInt;             {Current file position}
  83.       BufP : ^BufferArray;        {Pointer to text buffer}
  84.       Bpos : Word;                {Current position within buffer}
  85.       Bcnt : Word;                {Count of characters in buffer}
  86.       Bsize : Word;               {Size of text buffer, 0 if none}
  87.       UserData : array[15..16] of Byte; {Remaining UserData}
  88.       Name : array[0..79] of Char;
  89.     end;
  90.  
  91. var
  92.   BResult : Word;                 {Internal IoResult}
  93.  
  94.   procedure AssignBack(var F : BackText; Fname : string);
  95.     {-Assign a backwards file to a file variable}
  96.   begin
  97.     if BResult = 0 then begin
  98.       Assign(file(F), Fname);
  99.       BResult := IoResult;
  100.     end;
  101.   end;
  102.  
  103.   procedure ResetBack(var F : BackText; BufSize : Word);
  104.     {-Reset a backwards file, allocating buffer}
  105.   var
  106.     BR : BackRec absolute F;
  107.   begin
  108.     if BResult = 0 then
  109.       with BR do begin
  110.         {Open file}
  111.         Reset(file(F), 1);
  112.         BResult := IoResult;
  113.         if BResult <> 0 then
  114.           Exit;
  115.  
  116.         {Seek to end}
  117.         Fpos := FileSize(file(F));
  118.         Seek(file(F), Fpos);
  119.         BResult := IoResult;
  120.         if BResult <> 0 then
  121.           Exit;
  122.  
  123.         {Allocate buffer}
  124.         if BufSize < 128 then
  125.           BufSize := 128;
  126.         if MaxAvail < BufSize then begin
  127.           BResult := 203;
  128.           Exit;
  129.         end;
  130.         GetMem(BufP, BufSize);
  131.         Bsize := BufSize;
  132.         Bcnt := 0;
  133.         Bpos := 0;
  134.       end;
  135.   end;
  136.  
  137.   function BoF(var F : BackText) : Boolean;
  138.     {-Return true when F is at beginning of file}
  139.   var
  140.     BR : BackRec absolute F;
  141.   begin
  142.     with BR do
  143.       BoF := (Fpos = 0) and (Bpos = 0);
  144.   end;
  145.  
  146.   function GetCh(var F : BackText) : Char;
  147.     {-Return next character from end of file}
  148.   var
  149.     BR : BackRec absolute F;
  150.     Bread : Word;
  151.   begin
  152.     with BR do begin
  153.       if Bpos = 0 then
  154.         {Buffer used up}
  155.         if Fpos > 0 then begin
  156.           {Unread file remains, first reposition file pointer}
  157.           Bread := Bsize;
  158.           Dec(Fpos, Bread);
  159.           if Fpos < 0 then begin
  160.             {Reduce the number of characters to read}
  161.             Inc(Bread, Fpos);
  162.             Fpos := 0;
  163.           end;
  164.           Seek(file(F), Fpos);
  165.           BResult := IoResult;
  166.           if BResult <> 0 then
  167.             Exit;
  168.  
  169.           {Refill buffer}
  170.           BlockRead(file(F), BufP^, Bread, Bcnt);
  171.           BResult := IoResult;
  172.           if BResult <> 0 then
  173.             Exit;
  174.  
  175.           {Remove ^Z's from end of buffer}
  176.           while (Bcnt > 0) and (BufP^[Bcnt] = ^Z) do
  177.             Dec(Bcnt);
  178.           Bpos := Bcnt;
  179.           if Bpos = 0 then begin
  180.             {At beginning of file}
  181.             GetCh := LF;
  182.             Exit;
  183.           end;
  184.  
  185.         end else begin
  186.           {At beginning of file}
  187.           GetCh := LF;
  188.           Exit;
  189.         end;
  190.  
  191.       {Return next character}
  192.       GetCh := BufP^[Bpos];
  193.       Dec(Bpos);
  194.     end;
  195.   end;
  196.  
  197.   procedure ReadLnBack(var F : BackText; var S : string);
  198.     {-Read next line from end of backwards file}
  199.   var
  200.     Slen : Byte absolute S;
  201.     Tpos : Word;
  202.     Tch : Char;
  203.     T : string;
  204.   begin
  205.     Slen := 0;
  206.     if (BResult = 0) and not BoF(F) then begin
  207.       {Build string from end backwards}
  208.       Tpos := 256;
  209.       repeat
  210.         Tch := GetCh(F);
  211.         if BResult <> 0 then
  212.           Exit;
  213.         if Tpos > 1 then begin
  214.           Dec(Tpos);
  215.           T[Tpos] := Tch;
  216.         end;
  217.         {Note that GetCh arranges to return LF at beginning of file}
  218.       until Tch = LF;
  219.       {Transfer to result string}
  220.       Slen := 255-Tpos;
  221.       if Slen > 0 then
  222.         Move(T[Tpos+1], S[1], Slen);
  223.       {Skip over (presumed) CR}
  224.       Tch := GetCh(F);
  225.     end;
  226.   end;
  227.  
  228.   procedure CloseBack(var F : BackText);
  229.     {-Close backwards file, releasing buffer}
  230.   var
  231.     BR : BackRec absolute F;
  232.   begin
  233.     if BResult = 0 then
  234.       with BR do begin
  235.         Close(file(F));
  236.         BResult := IoResult;
  237.         if BResult <> 0 then
  238.           Exit;
  239.         FreeMem(BufP, Bsize);
  240.       end;
  241.   end;
  242.  
  243.   function BackResult : Word;
  244.     {-Return I/O status code from operation}
  245.   begin
  246.     BackResult := BResult;
  247.     BResult := 0;
  248.   end;
  249.  
  250. begin
  251.   BResult := 0;
  252. end.